﻿/*
    This file is part of nDoctor Light

    NDoctor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NDoctor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with NDoctor.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Probel.Ldoc.Dal.Configuration
{
    using AutoMapper;

    using Probel.Ldoc.Dal.Entities;
    using Probel.Ldoc.Services.Dto;

    internal class AutoMapperMapping
    {
        #region Methods

        internal void Configure()
        {
            #region Entity => Dto

            Mapper.CreateMap<Patient, PatientCardDto>()
                .ForMember(dest => dest.IsFemale, opt => opt.ResolveUsing<GenderToBool>());
            Mapper.CreateMap<Doctor, DoctorCardDto>()
                .ForMember(dest => dest.IsFemale, opt => opt.ResolveUsing<GenderToBool>());
            Mapper.CreateMap<Doctor, DoctorDto>()
                .ForMember(dest => dest.IsFemale, opt => opt.ResolveUsing<GenderToBool>());
            Mapper.CreateMap<Picture, PictureDto>()
                .ForMember(dest => dest.IdPatient, opt => opt.ResolveUsing<PictureToPatientId>());

            Mapper.CreateMap<MedicalRecord, RecordCardDto>();
            Mapper.CreateMap<Patient, ExpandedPatientCardDto>();
            Mapper.CreateMap<Patient, ExpandedPatientDto>();
            Mapper.CreateMap<Macro, MacroDto>();
            Mapper.CreateMap<Address, AddressDto>();
            Mapper.CreateMap<Macro, MacroDto>();
            Mapper.CreateMap<Profession, ProfessionCardDto>();
            Mapper.CreateMap<Insurance, InsuranceCardDto>();
            Mapper.CreateMap<Practice, PracticeCardDto>();
            Mapper.CreateMap<Reputation, ReputationCardDto>();
            Mapper.CreateMap<SearchTag, TagDto>();
            Mapper.CreateMap<Insurance, InsuranceDto>();
            Mapper.CreateMap<Practice, PracticeDto>();
            Mapper.CreateMap<Tag, SpecialisationDto>();

            Mapper.CreateMap<MedicalRecordState, RecordStateCardDto>().ForMember(dest => dest.RecordId
                                                                               , opt => opt.MapFrom(src => src.MedicalRecord.Id));
            Mapper.CreateMap<Tag, RecordDrawerCardDto>().ForMember(dest => dest.Title
                                                                 , opt => opt.MapFrom(src => src.Name));

            Mapper.CreateMap<Practice, string>().ConvertUsing(src => { return (src != null) ? src.Name : string.Empty; });
            Mapper.CreateMap<Insurance, string>().ConvertUsing(src => { return (src != null) ? src.Name : string.Empty; });
            Mapper.CreateMap<Tag, string>().ConvertUsing(src => { return (src != null) ? src.Name : string.Empty; });
            Mapper.CreateMap<Profession, string>().ConvertUsing(src => { return (src != null) ? src.Name : string.Empty; });
            Mapper.CreateMap<Reputation, string>().ConvertUsing(src => { return (src != null) ? src.Name : string.Empty; });

            #endregion

            #region Dto => Entity
            Mapper.CreateMap<DoctorDto, Doctor>();
            Mapper.CreateMap<RecordCardDto, MedicalRecord>();
            Mapper.CreateMap<MacroDto, Macro>();
            Mapper.CreateMap<PatientCardDto, Patient>();
            Mapper.CreateMap<TagDto, SearchTag>();
            Mapper.CreateMap<ProfessionCardDto, Profession>();
            Mapper.CreateMap<ReputationCardDto, Reputation>();
            Mapper.CreateMap<InsuranceDto, Insurance>();
            Mapper.CreateMap<InsuranceCardDto, Insurance>();
            Mapper.CreateMap<PracticeDto, Practice>();
            Mapper.CreateMap<AddressDto, Address>();
            Mapper.CreateMap<DoctorCardDto, Doctor>();
            Mapper.CreateMap<PracticeCardDto, Practice>();

            Mapper.CreateMap<SpecialisationDto, Tag>().ForMember(dest => dest.Category,
                                                                 opt => opt.MapFrom(src => TagCategory.Doctor));

            Mapper.CreateMap<RecordDrawerCardDto, Tag>().ForMember(dest => dest.Category,
                                                                    opt => opt.MapFrom(src => TagCategory.MedicalRecord))
                                                        .ForMember(dest => dest.Name,
                                                                    opt => opt.MapFrom(src => src.Title));

            //Ignoring all the related entity. This mapping should be done manually
            Mapper.CreateMap<ExpandedPatientDto, Patient>()
                .ForMember(dest => dest.Appointments, opt => opt.Ignore())
                .ForMember(dest => dest.BmiHistory, opt => opt.Ignore())
                .ForMember(dest => dest.Father, opt => opt.Ignore())
                .ForMember(dest => dest.Height, opt => opt.Ignore())
                .ForMember(dest => dest.IllnessHistory, opt => opt.Ignore())
                .ForMember(dest => dest.IsDeactivated, opt => opt.Ignore())
                .ForMember(dest => dest.MedicalRecords, opt => opt.Ignore())
                .ForMember(dest => dest.Mother, opt => opt.Ignore())
                .ForMember(dest => dest.Pictures, opt => opt.Ignore())
                .ForMember(dest => dest.PrescriptionDocuments, opt => opt.Ignore())
                .ForMember(dest => dest.Tag, opt => opt.Ignore())
                .ForMember(dest => dest.IsComplete, opt => opt.Ignore())
                .ForMember(dest => dest.SearchTags, opt => opt.Ignore())
                .ForMember(dest => dest.Doctors, opt => opt.Ignore())
                .ForMember(dest => dest.Profession, opt => opt.Ignore())
                .ForMember(dest => dest.Insurance, opt => opt.Ignore())
                .ForMember(dest => dest.Practice, opt => opt.Ignore())
                .ForMember(dest => dest.Reputation, opt => opt.Ignore())
                .ForMember(dest => dest.SearchTags, opt => opt.Ignore());

            #endregion

            #region Entity => Entity
            Mapper.CreateMap<MedicalRecord, MedicalRecordState>().ForMember(dest => dest.Id, opt => opt.Ignore());
            #endregion
        }

        #endregion Methods

        #region Nested Types

        private class GenderToBool : ValueResolver<Person, bool>
        {
            #region Methods

            protected override bool ResolveCore(Person source)
            {
                return source.Gender == Gender.Female;
            }

            #endregion Methods
        }

        private class PictureToPatientId : ValueResolver<Picture, long>
        {
            #region Methods

            protected override long ResolveCore(Picture source)
            {
                return source.Patient.Id;
            }

            #endregion Methods
        }

        #endregion Nested Types
    }
}